home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
dosnos2.arc
/
DOSKNOW2.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-01-19
|
62KB
|
1,526 lines
PAGE 60,132
TITLE Main routine for DosKnows Series
SUBTTL Calls upon routines in Convrs.asm
;-----------------------------------------------------------------------;
; Dosknows Oct 30, 1985 Version 1.20 ;
; ;
; This program tells you of all (in the sense, that I put them ;
; there) the things it knows of your hardware and operating environ- ;
; ment. You can do anything you want with it. If you add some ;
; things to it, let me know. I really would like to see the amount ;
; of memory in a system, amount free, amount used up by this pgm. ;
; Well, that is exactly what this new version has added. ;
; ;
; For those who've been putting off trying to learn assembler, ;
; try this. I've commented things a lot, maybe it can help. ;
; ;
; By the way, you'll also need covers.asm, and the makefile ;
; will help you masm and link it. ;
; ;
; January 19, 1986 -- Update ;
; ;
; This new version of dosknows also displays the amount of ;
; memory being used, free, and total in the system. It took ;
; a while to find it, but its not in here. Procedure SHOWMEM ;
; is the new procedure called from within the procedure ;
; MOREPSP. ;
; ;
; The file convers.asm has not been affected by this addition. ;
; ;
; Anil Bharvaney ;
; Compuserve 72057,1103 ;
;-----------------------------------------------------------------------;
EXTRN Stdin:Near, Stdout:Near, Strout:Near, ToHex:Near
EXTRN ToDec:Near, ToDecW:Near
SUBTTL All major equates are placed here
PAGE
;-------------------------------------------------------;
; ALL MAJOR EQUATES ARE PLACED RIGHT BELOW ;
;-------------------------------------------------------;
DOS EQU 21H
CR EQU 0DH
LF EQU 0AH
TAB EQU 09H
TERMINATOR EQU '$' ;dos string terminator
ENVAREA EQU 2CH ;offset into psp for start of environment
SEGLEFT EQU 06H ;offset into psp for bytes remainging in segment
PGMTERMINATE EQU 0AH ;offset into psp for program terminate handler
CONTROL_C EQU 0EH ;offset into psp for Control C exit handler
CRITICAL EQU 12H ;offset into psp for critical error handler
CURRDISK EQU 19H ;dos func for inquiring current drive
LOGDISK EQU 0EH ;dos func to log to a drive
GETDATE EQU 2AH ;dos func to get date
GETTIME EQU 2CH ;dos func to get time
GETVERSION EQU 30H ;dos func to get version #
CTRLCHECK EQU 33H ;dos func to get ^c check status
GETINTVEC EQU 35H ;dos func to get int vector address
DISKSPACE EQU 36H ;dos func to get disk information
COUNTRYINFO EQU 38H ;dos func to get country dependent info
CDIR EQU 47H ;dos func to get current directory text
VERIFY EQU 54H ;dos func to return status of verify on write
SUBTTL Stack is defined here
PAGE
SSEG SEGMENT STACK
DW 128 DUP(?)
SSEG ENDS
SUBTTL Data Segment for this source file is here
PAGE
DSEG SEGMENT PUBLIC PARA 'DATA'
MSG0 DB 'Program Started : ',Terminator ;*
MSG1 DB 'Program Segment Address is at : ',Terminator ;*
MSG2 DB 'Environment Space begins at : ',Terminator ;*
MSG2A DB 'Environment Space contains:',CR,LF,Terminator ;*
MSG3 DB 'Bytes left in current segment : ',Terminator ;*
MSG3A DB 'Total memory found : ',Terminator
MSG3B DB 'Memory being used : ',Terminator
MSG3C DB 'Memory free : ',Terminator
MSG3D DB ' bytes',Terminator
MSG4 DB 'Current logged drive is : ',Terminator ;*
MSG5 DB 'Current Directory is : ',Terminator ;*
MSG6 DB 'Number of logical drives found : ',Terminator ;*
MSG7 DB 'Logged Drive Statistics:',CR,LF,Terminator ;*
MSG8 DB ' Number of available clusters : ',Terminator ;*
MSG9 DB ' Number of clusters per drive : ',Terminator ;*
MSG10 DB ' Number of bytes per sector : ',Terminator ;*
MSG11 DB ' Number of sectors per cluster : ',Terminator ;*
MSG12 DB ' Bytes used on current drive : ',Terminator ;*
MSG13 DB ' Bytes remaining on current drive: ',Terminator ;*
MSG13A DB ' Bytes capacity of current drive : ',Terminator ;*
MSG14 DB ' Write verify for drive is : ',Terminator ;*
MSG15 DB 'DOS version number is : ',Terminator ;*
MSG16 DB 'OEM number is : ',Terminator ;*
MSG17 DB 'User number is : ',Terminator ;*
MSG18 DB 'Control C check (Break status) is : ',Terminator ;*
MSG19 DB 'Interrupt Vector Addresses:',CR,LF,TERMINATOR ;*
MSG20 DB ' Program terminate address (20H) : ',Terminator ;*
MSG21 DB ' DOS function request addr (21H) : ',Terminator ;*
MSG22 DB ' Terminate address (22H) : ',Terminator ;*
MSG23 DB ' Control C exit address (23H) : ',Terminator ;*
MSG24 DB ' Fatal error abort address (24H) : ',Terminator ;*
MSG25 DB 'Address from Program Segment Prefix:',CR,LF,TERMINATOR ;*
MSG26 DB ' Program terminate address (22H) : ',Terminator ;*
MSG27 DB ' Control-C address (23H) : ',Terminator ;*
MSG28 DB ' Critical err handler addr (24H) : ',Terminator ;*
MSG29 DB 'Country Dependent Information:',CR,LF,TERMINATOR
USA DB ' Set for USA standard h:m:s m/d/y',CR,LF,TERMINATOR
EUROPE DB ' Set for EUROPE h:m:s d/m/y',CR,LF,TERMINATOR
JAPAN DB ' Set for JAPAN y/m/d h:m:s',CR,LF,TERMINATOR
MSG30 DB ' Currency symbol defined : ',Terminator
MSG31 DB ' Thousands separator : ',Terminator
MSG32 DB ' Decimal separator : ',Terminator
MSG33 DB ' Date separator : ',Terminator
MSG34 DB ' Time separator : ',Terminator
BIT00 DB ' Currency symbol precedes amount',CR,LF,TERMINATOR
BIT01 DB ' Currency symbol comes after amount',CR,LF,TERMINATOR
BIT10 DB ' Currency symbol immediately precedes amount',CR,LF,TERMINATOR
BIT11 DB ' Is a space between currency symbol and amount',CR,LF,TERMINATOR
MSG35 DB ' Number of decimal places shown : ',Terminator
MSG36 DB ' Time format is : ',Terminator
MSG37 DB ' Location of case mapping routine: ',Terminator
MSG38 DB ' Data list separator symbol : ',Terminator
ON DB 'ON',CR,LF,TERMINATOR
OFF DB 'OFF',CR,LF,TERMINATOR
FORM12 DB '12 hour format',CR,LF,TERMINATOR
FORM24 DB '24 hour format',CR,LF,TERMINATOR
ERRMSG DB 'Properly installed only for DOS Versions above 2.00',CR,LF,TERMINATOR
ERR1 DB 'Ouch! Dos refused to tell me! Sob, sob, sob.',CR,LF,Terminator
SORRY DB 'Sorry, there is something wrong.',TERMINATOR
MORE DB 'Press any key to continue.....',Terminator
CURDRIV DB ? ;current drive, 0=a:, 1=b:
USED_1 DW ? ;bytes used on disk
USED_2 DW ? ;
FREE_1 DW ? ;free space on disk
FREE_2 DW ?
TOTAL_1 DW ? ;avai space on disk
TOTAL_2 DW ?
MAJVERS DB ? ;major version #
MINVERS DB ? ;minor version #
PSP DW ? ;keep psp segment address here
MEMTOP DW ? ;top of memory in paragraph form
MEMBOT DW ? ;bottom of memory in paragraph form
ENV DW ? ;segment of environment variable strings
MSG_TABLE LABEL WORD
DW OFFSET MSG20
DW OFFSET MSG21
DW OFFSET MSG22
DW OFFSET MSG23
DW OFFSET MSG24
CTRY_INFO LABEL BYTE
DATE_TIME_FORMAT DW ?
CURRENCY_SYMBOL DB 5 DUP (?)
THOUSANDS_SEPARATOR DW ?
DECIMAL_SEPARATOR DW ?
DATE_SEPARATOR DW ?
TIME_SEPARATOR DW ?
BIT_FIELD DB ?
CURRENCY_PLACES DB ?
TIME_FORMAT DB ?
CASE_MAPPING_CALL DW 2 DUP (?)
DATA_LIST_SEPARATOR DW ?
DAYS LABEL BYTE
DB 'Sun',TERMINATOR
DB 'Mon',TERMINATOR
DB 'Tue',TERMINATOR
DB 'Wed',TERMINATOR
DB 'Thu',TERMINATOR
DB 'Fri',TERMINATOR
DB 'Sat',TERMINATOR
MONTHS LABEL BYTE
DB 'Jan',TERMINATOR
DB 'Feb',TERMINATOR
DB 'Mar',TERMINATOR
DB 'Apr',TERMINATOR
DB 'May',TERMINATOR
DB 'Jun',TERMINATOR
DB 'Jul',TERMINATOR
DB 'Aug',TERMINATOR
DB 'Sep',TERMINATOR
DB 'Oct',TERMINATOR
DB 'Nov',TERMINATOR
DB 'Dec',TERMINATOR
WORKSPACE DB 64 DUP(?)
DSEG ENDS
SUBTTL MACROS
PAGE
PUTH MACRO
PUSH AX
MOV AL,'H'
CALL Stdout
POP AX
ENDM
PUTC MACRO CHAR
PUSH AX
MOV AL,CHAR
CALL Stdout
POP AX
ENDM
CRLF MACRO
PUSH AX
MOV AL,CR
CALL Stdout
MOV AL,LF
CALL Stdout
POP AX
ENDM
CLEAR_SCREEN MACRO
LOCAL LABEL
PUSH CX
PUSH AX
MOV CX,25
LABEL:
MOV AL,CR
CALL Stdout
MOV AL,LF
CALL Stdout
LOOP LABEL
POP AX
POP CX
ENDM
SUBTTL Code segment begins here, at last
PAGE
CSEG SEGMENT PUBLIC PARA 'CODE'
ASSUME CS:CSEG,DS:DSEG,SS:SSEG,ES:NOTHING
MAIN PROC FAR
PUSH DS ;has psp address
XOR AX,AX
PUSH AX ;two pushes for far return to DOS
;save the psp segment
MOV DX,DS ;save the psp
;establish addressiblity to the data
MOV AX,SEG DSEG ;get data segment address
MOV DS,AX ;make it our data segment
MOV PSP,DX ;save it in memory location also
CLEAR_SCREEN ;clear out the screen
CALL DATENOW ;print out startup message
CALL TIMENOW ;print out the current time
CRLF ;put in blank line
CALL MOREPSP ;tells more about PSP known items
CALL PAGE_BREAK ;page may be full, wait for user to see
CALL CURRENT_DRIVE ;tells everything about the current drive
CALL VERSION ;tells you all about dos version #'s
CALL BREAKST ;^C break status
CALL PAGE_BREAK ;page is full, wait till user press's any key
CALL INTVEC_ADDRESS ;show the interrupt handler addresses (dos)
CALL INTVEC_PSP ;shows the same from psp information
CALL PAGE_BREAK ;page is full, wait for user to say continue
CALL VERSION_RQT ;see if the version is above 2.00
CALL FILL_INFO ;fill our structure with country information
CMP AX,0 ;1 if it failed
JE NEXT ;if all is ok, continue
JMP NODO ;failed
NEXT: ;get here if all goes well
CALL HOLMES ;holmes deciphers all into english.
JMP GET_OUT ;and exit program
NODO:
LEA DX,SORRY ;show message of failure
CALL STROUT ;display message
JMP GET_OUT ;and exit program
GET_OUT:
RET ;return to DOS
MAIN ENDP
SUBTTL print this string until a null is seen DISPZ
PAGE
;-------------------------------------------------------;
; Procedure: DispZ ;
; Will display to console the contents of an ;
; asciiz string ;
; ;
; Input: ;
; DS:SI points to the asciiz string. ;
; Output: ;
; Asciiz string printed on console. ;
;-------------------------------------------------------;
DISPZ PROC NEAR
PUSH AX ;save the registers
PUSH SI
DISPZ1:
LODSB ;get the first character
CMP AL,0 ;is it the end of the string
JE DISPZ_DONE ;yes, it is get out
CALL STDOUT ;go display the character.
JMP DISPZ1 ;repeat until null is found
DISPZ_DONE:
CRLF ;put a crlf pair
POP SI ;restore those registers
POP AX
RET
DISPZ ENDP
SUBTTL deciphers the contents of ctry_info into english
PAGE
;-------------------------------------------------------;
; Procedure: Holmes ;
; The best around to do this kind of snooping ;
; around. ;
; Input: ;
; Works on ctry_info ;
; Output: ;
; Tells a lot about it in english onto the crt. ;
;-------------------------------------------------------;
HOLMES PROC NEAR
PUSH AX ;save callers registers
PUSH DX
PUSH SI
;deal with the date/time format (word) first
MOV AX,DATE_TIME_FORMAT ;tells some thing like
CMP AX,0 ;is if usa standard
JE USALOC ;display usa msg
CMP AX,1 ;ok, the european format?
JE EUROPELOC ;display europe format
CMP AX,2 ;ok, japanese format?
JE JAPANLOC ;display japan msg (in english)
LEA DX,ERR1 ;display, unknown country format
JMP CTRY1 ;go print it
USALOC: LEA DX,USA ;point to usa format
JMP CTRY1 ;go print it
EUROPELOC:
LEA DX,EUROPE ;point to europe format
JMP CTRY1 ;go print it
JAPANLOC:
LEA DX,JAPAN ;point to japan format
CTRY1: CALL STROUT ;print it out
;deal with the currency symbol (5 bytes)
LEA DX,MSG30 ;point to heading string
CALL STROUT ;print it out
LEA SI,CURRENCY_SYMBOL ;point to the symbol string
CALL DISPZ ;this will display the string
;display the thousands separator (2 bytes)
LEA DX,MSG31 ;point to the heading string
CALL STROUT ;print the string out
LEA SI,THOUSANDS_SEPARATOR ;point to the string
CALL DISPZ ;print it out
;deal with the decimal separator (2 bytes)
LEA DX,MSG32 ;point to the heading string
CALL STROUT ;print the string out
LEA SI,DECIMAL_SEPARATOR ;point to the string
CALL DISPZ ;print it out
;deal with the date separator (2 bytes)
LEA DX,MSG33 ;point to the heading string
CALL STROUT ;print the string out
LEA SI,DATE_SEPARATOR ;point to the string
CALL DISPZ ;print it out
;deal with the time separator (2 bytes)
LEA DX,MSG34 ;point to the heading string
CALL STROUT ;print the string out
LEA SI,TIME_SEPARATOR ;point to the string
CALL DISPZ ;print it out
;deal with the currency places (1 byte)
LEA DX,MSG35 ;point to the header
CALL STROUT ;print it out
MOV AL,CURRENCY_PLACES ;load it from its hiding place
ADD AL,'0' ;make it ascii decimal
CALL STDOUT ;print the digit out
CRLF ;put a cr/lf pair
;deal with the time format (1 byte)
LEA DX,MSG36 ;point to the header
CALL STROUT ;print the header to tty
MOV AL,TIME_FORMAT ;restore its value
CMP AL,0 ;is it 12 hour format?
JE FMT12 ;yes 12 hour one
CMP AL,1 ;is it 24 hour format?
JE FMT24 ;yes 24 hour one
LEA DX,ERR1 ;display error otherwise
JMP TFMT_END ;all meet here for printing
FMT12: LEA DX,FORM12 ;set to 12 hour format line
JMP TFMT_END ;all meet here for printing
FMT24: LEA DX,FORM24 ;set to 24 hour format line
TFMT_END:
CALL STROUT ;print the string out
;deal with the data list separator (2 bytes)
LEA DX,MSG38 ;point to the heading string
CALL STROUT ;print the string out
LEA SI,DATA_LIST_SEPARATOR ;point to the string
CALL DISPZ ;print it out
;deal with the case mapping call (4 bytes)
LEA DX,MSG37 ;point to the heading line
CALL STROUT ;print the string
LEA SI,CASE_MAPPING_CALL ;get the address of variable
MOV DX,WORD PTR [SI] ;get the segment of the routine
CALL TOHEX ;print it out in hex
MOV DX,WORD PTR [SI+2] ;get the offset addr of the routine
CALL TOHEX ;print it in hex
PUTH ;put the H to make it hexidecimal
CRLF ;put a cr/lf pair
;deal with the bitfield (1 byte)
MOV AH,BIT_FIELD ;get the bitfield pattern
AND AH,00000001B ;is bit zero set
CMP AH,00000001B ;
JE BIT0SET ;bit 0 is set
LEA DX,BIT00 ;bit 0 is 0
JMP NEXTBIT ;deal with the next bit
BIT0SET:
LEA DX,BIT01 ;bit 0 is 1
NEXTBIT:
CALL STROUT ;print the string out
MOV AH,BIT_FIELD ;recover the bit field
AND AH,00000010B ;is bit 1 set
CMP AH,00000010B ;
JE BIT1SET ;bit 1 is 1
LEA DX,BIT10 ;bit 1 is not set
JMP ENDBIT ;end of this field
BIT1SET:
LEA DX,BIT11 ;bit 1 is set to 1
ENDBIT:
CALL STROUT ;print the string out
POP SI ;restore callers registers
POP DX
POP AX
RET
HOLMES ENDP
SUBTTL Fill the structure in dseg with country information
PAGE
;-------------------------------------------------------;
; Procedure : Fill_Info ;
; Fill the structure in dseg, ctry_info with the ;
; values returned by dos. ;
; ;
; Input: None: ;
; Output: filled structure ctry_info ;
;-------------------------------------------------------;
FILL_INFO PROC NEAR
PUSH DX ;save callers registers
CLC ;clear the carry flag
MOV AH,COUNTRYINFO ;func to get country information
MOV AL,0 ;req in dos 2.00
LEA DX,CTRY_INFO ;this is where the 32bytes are going
INT DOS
JC NOTOK ;if carry is set, we failed
XOR AX,AX ;0 means its done
JMP FILL_DONE ;and return
NOTOK:
MOV AX,1 ;1 means it failed
CLC ;clear the carry
FILL_DONE:
POP DX ;restore registers
RET
FILL_INFO ENDP
SUBTTL For country_info need dos above 2.00, see if this is true
PAGE
;-------------------------------------------------------;
; Procedure: Version_rqt ;
; Determines if this is a version of dos above ;
; 2.00. If it is not, it will display a message ;
; to that effect. ;
; ;
; Input: ;
; Looks at Majvers and Minvers in the dseg ;
; Output: ;
; If too low, will show message. ;
;-------------------------------------------------------;
VERSION_RQT PROC NEAR
PUSH AX ;save callers registers
PUSH DX
LEA DX,MSG29 ;point to heading string
CALL STROUT ;print it out
CRLF ;put a blank line
MOV AH,MAJVERS ;get the major version #
CMP AH,2 ;is it 2
JB TOOLOW ;not even dos2.0
MOV AH,MINVERS ;get the minor version #
CMP AH,0 ;is it greater than 0
JNZ OK ;if non zero, all is fine
TOOLOW:
LEA DX,ERRMSG ;tell them they're too low !
CALL STROUT ;print it out
CRLF ;print a blank line
OK:
POP DX ;restore the registers
POP AX
RET
VERSION_RQT ENDP
SUBTTL Get interrupt handler addresses from DOS
PAGE
;-------------------------------------------------------;
; Procedure: IntVec_Address ;
; Determines interrupt handler address locations ;
; by asking dos. Currently implemented for ;
; vectors 20H - 24H ;
; ;
; Input: ;
; None ;
; Output: ;
; Interrupt handler addresses and prompts dis- ;
; played on the console. ;
;-------------------------------------------------------;
INTVEC_ADDRESS PROC NEAR
PUSH AX ;save callers registers
PUSH BX
PUSH DX
PUSH DI
PUSH ES
XOR DI,DI ;intialize the counter
LEA DX,MSG19 ;heading for what we're doing
CALL STROUT ;print it to the console
INT_LOOP:
PUSH DI ;save counter
SHL DI,1 ;offsets are two bytes long
MOV DX,MSG_TABLE[DI] ;get the appropriate msg for the int
CALL STROUT ;print it to the console
POP DI ;restore di to count
MOV AX,0020H ;intialize to base counter
ADD AX,DI ;that is the int handler of interest
PUSH AX ;save this counter.
MOV AH,GETINTVEC ;dos func# for int handler address
INT DOS ;ask dos to get it
MOV DX,ES ;that's the interrupt segment address
CALL TOHEX ;print it out.
MOV DX,BX ;that's the interrupt offset address
CALL TOHEX ;print it out
PUTH ;to denote its hex
CRLF ;and lets go to the next line
INC DI ;increment counter
POP AX ;restore register for comparision
CMP AL,24H ;are we done yet?
JNE INT_LOOP ;no, so repeat it
POP ES
POP DI
POP DX
POP BX
POP AX
RET
INTVEC_ADDRESS ENDP
SUBTTL Get interrupt handler addresses from the PSP
PAGE
;-------------------------------------------------------;
; Procedure Intvec_Psp ;
; Gets the location of interrupt handlers by ;
; peeking around the PSP. Currently implemented ;
; for interrupts: 20H, 23H, and 24H ;
; ;
; Input: ;
; reads memory variable PSP for PSP segment addr. ;
; Output: ;
; outputs handler addresses to the console. ;
;-------------------------------------------------------;
INTVEC_PSP PROC NEAR
PUSH AX ;save callers registers
PUSH DX
PUSH SI
PUSH ES
MOV ES,PSP
CRLF ;add some spacing
LEA DX,MSG25 ;point to the next message
CALL STROUT ;print that string out
LEA DX,MSG26 ;point to next message
CALL STROUT ;print the string out
MOV SI,PGMTERMINATE ;offset in psp of int handler location
MOV DX,ES:WORD PTR[SI+2] ;get that word segment
CALL TOHEX ;print it out in hex
MOV DX,ES:WORD PTR[SI] ;get the word offset
CALL TOHEX ;print it out in hex
PUTH ;put h to denote hex
CRLF ;put cr/lf character
LEA DX,MSG27 ;point to next message
CALL STROUT ;print the string out
MOV SI,CONTROL_C ;offset in psp of int handler location
MOV DX,ES:WORD PTR[SI+2] ;get that word segment
CALL TOHEX ;print it out in hex
MOV DX,ES:WORD PTR[SI] ;get the word offset
CALL TOHEX ;print it out in hex
PUTH ;put h to denote hex
CRLF ;put cr/lf character
LEA DX,MSG28 ;point to next message
CALL STROUT ;print the string out
MOV SI,CRITICAL ;offset in psp of int handler location
MOV DX,ES:WORD PTR[SI+2] ;get that word segment
CALL TOHEX ;print it out in hex
MOV DX,ES:WORD PTR[SI] ;get the word offset
CALL TOHEX ;print it out in hex
PUTH ;put h to denote hex
CRLF ;put cr/lf character
POP ES ;restore callers register
POP SI
POP DX
POP AX
RET
INTVEC_PSP ENDP
SUBTTL Procedure BreakSt
PAGE
;-------------------------------------------------------;
;Procedure: BreakSt ;
; Determines ^C break status ;
;IN: ;
; None ;
;OUT: ;
; Prints on/off to the console ;
;-------------------------------------------------------;
BREAKST PROC NEAR
PUSH AX ;save callers registers
PUSH DX ;
LEA DX,MSG18 ;ready to print out ^C check prompt
CALL STROUT ;print it out
MOV AH,CTRLCHECK ;dos func # for ^C check
XOR AL,AL ;requesting only
INT DOS ;ask dos
CMP DL,0 ;is ^C check off
JZ COFF ;^c check is off
LEA DX,ON ;otherwise it is on
JMP CMEET ;print it
COFF: LEA DX,OFF ;^C check is off
CMEET: CALL STROUT ;print out the result
POP DX ;restore caller registers
POP AX
RET
BREAKST ENDP
SUBTTL Procedure Version
PAGE
;-------------------------------------------------------;
; Procedure: Version ;
; Gets the dos version #'s ;
; IN: ;
; Nothing ;
; OUT: ;
; Prints out major,minor,oem,user #'s, and stores ;
; major and minor #'s into DSEG:MajVers and ;
; DSEG:MinVers ;
;-------------------------------------------------------;
VERSION PROC NEAR
PUSH AX ;save callers registers
PUSH BX
PUSH CX
PUSH DX
MOV AH,GETVERSION ;dos funciton to get version #
INT DOS ;tell dos to do it
;al = major version
;ah = minor version
;bh = oem number
;bl:cx = user # (24 bits)
; print the version #'s
MOV MAJVERS,AL ;save major version #
MOV MINVERS,AH ;save minor version #
LEA DX,MSG15 ;dos version #
CALL STROUT ;print banner
MOV DL,AL ;move character to convert to decimal
CALL ToDec ;convert to decimal
PUTC '.' ;put the holy period
MOV DL,AH ;print the minor part
CMP DL,09 ;need preceeding 0 if needed
JA NOZERO ;don't need a zero
PUTC '0' ;put in a zero
NOZERO: CALL ToDec ;convert to decimal and print
CRLF ;put CRLF pair
;print the oem number
LEA DX,MSG16 ;print oem # banner
CALL STROUT ;print it out
MOV DL,BH ;get the oem #
CALL TODEC ;print it out in decimal
CRLF ;put a cr/lf pair
;print the user number
LEA DX,MSG17 ;print user # banner
CALL STROUT ;print the banner out
XOR DH,DH ;zero out the top
MOV DL,BL ;bl:cx has user number
CALL TOHEX ;print the bl portion
MOV DX,CX ;print the lower portion
CALL TOHEX ;print the cx portion
PUTH ;put the H for hex notation
CRLF ;put a cr/lf pair
POP DX ;restore user registers
POP CX
POP BX
POP AX
RET
VERSION ENDP
SUBTTL Procedure CalcDisk
PAGE
;-------------------------------------------------------;
; Procedure: CalcDisk ;
; Calculates diskspace free and total available ;
; IN: ;
; AX - sectors/clusters ;
; BX - available clusters ;
; CX - bytes per sector ;
; DX - clusters per drive ;
; ;
; OUT: ;
; DSEG:USED DD has used diskspace figure ;
; DSEG:FREE DD has free diskspace figure ;
; DSEG:TOTAL DD has total diskspace on disk ;
;-------------------------------------------------------;
CALCDISK PROC NEAR
PUSH AX ;save all registers
PUSH BX ;
PUSH CX
PUSH DX
PUSH SI
MOV SI,DX ;copy total
SUB SI,BX ;used = total - free
PUSH DX ;temporary save, total
PUSH BX ;available
MOV BX,CX ;common part, bytes/cluster computed
XOR DX,DX ;don't need top, AX->sectors/cluster
MUL BX ;sect/clust x bytes/sector=bytes/clust
MOV TOTAL_1,DX ;save bytes/clust
MOV TOTAL_2,AX ;
MOV USED_1,DX ;
MOV USED_2,AX ;
POP BX ;restore available clusters
MUL BX ;bytes/clust * avail clust=free_sp
MOV FREE_1,DX ;free disk space msw
MOV FREE_2,AX ;free disk space lsw
POP BX ;pop clusters/drive
MOV DX,TOTAL_1 ;restore bytes/cluster
MOV AX,TOTAL_2 ;
MUL BX ;bytes/cluster*# clusters on drive=avail
MOV TOTAL_1,DX ;max space on disk msw
MOV TOTAL_2,AX ;max space on disk lsw
MOV DX,USED_1 ;restore bytes/cluster
MOV AX,USED_2 ;
MOV BX,SI ;# of clusters used
MUL BX ;bytes/cluster x #clusters used = used
MOV USED_1,DX ;save this information, msw
MOV USED_2,AX ;lsw.
POP SI ;restore all registers
POP DX ;restore all registers
POP CX
POP BX
POP AX
RET
CALCDISK ENDP
SUBTTL Procedure Current_Drive
PAGE
;-------------------------------------------------------;
;Procedure: Current_Drive ;
; Tells everything about the drive (current) ;
;In: ;
; None. ;
;Out: ;
; Stores current drive # in Dseg:Curdriv ;
;-------------------------------------------------------;
CURRENT_DRIVE PROC NEAR
PUSH AX ;save callers registers
PUSH BX ;save caller's registers
PUSH CX
PUSH DX
PUSH SI
;Get the current drive number A=0, B=1 and store it in memory
LEA DX,MSG4 ;tell the world which drive is current
CALL Strout ;print the prompt
MOV AH,CurrDisk ;func # for current disk information
INT DOS ;tell dos
MOV CURDRIV,AL ;save drive number
ADD AL,'A' ;make drive ascii
PUTC AL ;print drive letter
PUTC ':' ;and the colon
CRLF ;and go to the next line
;Print the current directory name
LEA DX,MSG5 ;prompt for current directory
CALL Strout ;print the prompt
MOV AH,CDIR ;func to get text of current directory
LEA SI,Workspace ;point to 64 byte area
MOV DL,CURDRIV ;that's the drive of interest
INC DL ;dos wants it 1=a,....
INT DOS ;tell dos to do it
JC Failed ;could not do it
LEA SI,Workspace ;point to the begining
PUTC '\' ;that is not usually given by dos
CD1:
MOV AL,BYTE PTR[SI] ;get a byte
CMP AL,0 ;is it the end of the string?
JE CDONE ; yes, then quit
CALL Stdout ;otherwise print the character
INC SI ;point to next character
JMP CD1
FAILED:
LEA DX,SORRY ;point to fail message
CALL Strout ;print it out
CDONE: CRLF ;terminate with cr/lf pair
;Print number of logical drives dos knows system has
LEA DX,MSG6 ;prompt for number of drives
CALL Strout ;print the prompt
MOV AH,LOGDISK ;log drive function
MOV DL,CURDRIV ;move curdrive as drive to log on to
INT DOS ;tell dos to do it
MOV DL,AL ;# drives attached moved to dl
CALL TODEC ;print it out in decimal
CRLF ;place cr/lf pair
;Print some information on logged drive
LEA DX,MSG7 ;banner for things following
CALL STROUT ;print out the banner
LEA DX,MSG8 ;# of avail clusters banner
CALL STROUT ;print it out
MOV AH,DISKSPACE ;func for free disk space
XOR DL,DL ;about the current drive
INT DOS ;ax= sec/cluster
;bx= avail clusters
;cx= bytes per drive
;dx = clusters per drive
CALL CALCDISK ;calculate freespace and max disk space
;display # of free clusters on drive
PUSH DX ;save dx
MOV DX,BX ;get ready to print in hex
CALL TOHEX ;print avail clusters
PUTH ;put H to represent Hexadecimal notation
CRLF ;print cr/lf pair
;display # clusters (total) on drive
LEA DX,MSG9 ;# clusters / drive msg
CALL STROUT ;print it out
POP DX ;this has it
CALL TOHEX ;print it out
PUTH ;print H to represent Hex notation
CRLF ;print cr/lf pair
;display # bytes / sector on drive
LEA DX,MSG10 ;# bytes / sector message
CALL STROUT ;print it out
MOV DX,CX ;ready to print in hex
CALL ToHex ;print it out
PUTH ;print H to represent Hex notation
CRLF ;print cr/lf pair
;display # sectors/cluster on drive
LEA DX,MSG11 ;# of sectors / cluster
CALL STROUT ;print out message
MOV DX,AX ;ready to print in hex
CALL TOHEX ;print in hex
PUTH ;print H to represent Hex notation
CRLF ;print cr/lf pair
;bytes used up on current disk
LEA DX,MSG12 ;bytes used on drive
CALL STROUT ;print out the message
MOV DX,USED_1 ;print msw
CALL TOHEX ;print msw in hex
MOV DX,USED_2 ;print lsw
CALL TOHEX ;print lsw in hex
PUTH ;print H to represent Hex notation
CRLF ;print cr/lf pair
; bytes remaining on disk
LEA DX,MSG13 ;remaining diskspace
CALL STROUT ;print message
MOV DX,FREE_1 ;the msw is ready
CALL TOHEX ;print it in hex
MOV DX,FREE_2 ;the lsw is ready
CALL TOHEX ;print the lsw
PUTH ;print H to represent Hex notation
CRLF ;print pair of cr/lf
; bytes in total supported by disk
LEA DX,MSG13A ;total drive capacity message
CALL STROUT ;print message
MOV DX,TOTAL_1 ;print msw
CALL TOHEX ;in hex
MOV DX,TOTAL_2 ;print lsw
CALL TOHEX ;in hex
PUTH ;print H to represent Hex notation
CRLF ;print cr/lf pair
;display status of verify after write
;0 is off and 1 is on
LEA DX,MSG14 ;verify status message
CALL STROUT ;print the message
MOV AH,VERIFY ;dos status chk func for verify
INT DOS ;ask dos to check it
CMP AL,0 ;is the flag off
JZ ISOFF ;is off
LEA DX,ON ;is on
JMP PR1 ;get ready to print
ISOFF: LEA DX,OFF ;is off
PR1: CALL STROUT ;print out the message
POP SI ;restore caller's registers,
POP DX
POP CX
POP BX
POP AX
RET
CURRENT_DRIVE ENDP
SUBTTL Shows the contents of environment area
PAGE
;-------------------------------------------------------;
; Procedure Showenv ;
; Displays the environment variables currently ;
; set onto the console. ;
; ;
; Input: ;
; Looks at the variable ENV ;
; that is set by MorePsp. ;
; Output: ;
; Displays the environment variable strings onto ;
; the console. ;
;-------------------------------------------------------;
SHOWENV PROC NEAR
PUSH AX ;save callers registers
PUSH DX
PUSH SI
PUSH DS
CRLF ;skip a line
LEA DX,MSG2A ;display a message
CALL STROUT ;print it out
CRLF ;skip a line
PUTC TAB ;tab one field
MOV SI,ENV ;point to the Env segment
MOV DS,SI ;and ready to start at the top
XOR SI,SI
ENVLP1:
LODSB ;get a character from Envsegment
CMP AL,0 ;is it the end of the string?
JE STRING_END ;if yes, place a cr/lf
ENVLP2:
CALL STDOUT ;if not, print the character out
JMP ENVLP1 ;get the next character
STRING_END: ;end of one string
CRLF ;put a cr/lf pair
LODSB ;get the next character
CMP AL,0 ;are we done?
JZ FIN ;if yes, scram
PUTC TAB ;otherwise, tab one field
JMP ENVLP2 ;if not, print the character out and loop
FIN: ;yes, we are done
CRLF ;add some spacing
POP DS ;restore things to normal
POP SI
POP DX
POP AX
RET
SHOWENV ENDP
;-------------------------------------------------------;
; Procedure Showmem ;
; Displays the knowledge of psp on the topic of ;
; memory. ;
; ;
; Input: ;
; Looks at the variable PSP ;
; that is set by main program ;
; Output: ;
; Displays the memory information. ;
;-------------------------------------------------------;
SHOWMEM PROC NEAR
PUSH AX ;save callers registers
PUSH BX
PUSH DX
PUSH ES
CRLF ;skip a line
LEA DX,MSG3A ;display a message
CALL STROUT ;print it out
;get the parameters from the psp
MOV AX,PSP ;get the psp segment value
MOV ES,AX ;es points to psp segment
MOV MEMBOT,AX ;psp is bot of memory for exe files, CS for COM
MOV DX,ES:WORD PTR [2] ;get the word at offset 2 in psp
MOV MEMTOP,DX ;which is top of memory in para form
;display information on total memory
PUTC '<' ;put the angle bracket
MOV DX,MEMTOP ;total memory in para form
CALL TOHEX ;convert to hex and display
PUTH ;make it known it is in hex
PUTC '>' ;put closing angle bracket
PUTC TAB ;some space
MOV AX,MEMTOP ;get ready to multiply
XOR DX,DX ;will be upper byte
MOV BX,10H ;multiply by 16
MUL BX ;dx = msw, ax = lsw
CALL TOHEX ;print most significant word first
MOV DX,AX ;print the lsw now
CALL TOHEX ;print it
PUTH ;make it known it is in hex
LEA DX,MSG3D ;add label
CALL STROUT ;print the label
CRLF ;skip line
;display information on memory currently used
CRLF ;skip a line
LEA DX,MSG3B ;display a message
CALL STROUT ;print it out
;display information on memory used
PUTC '<' ;put the angle bracket
MOV DX,MEMBOT ;used memory in para form
CALL TOHEX ;convert to hex and display
PUTH ;make it known it is in hex
PUTC '>' ;put closing angle bracket
PUTC TAB ;some space
MOV AX,MEMBOT ;get ready to multiply
XOR DX,DX ;will be upper byte
MOV BX,10H ;multiply by 16
MUL BX ;dx = msw, ax = lsw
CALL TOHEX ;print most significant word first
MOV DX,AX ;print the lsw now
CALL TOHEX ;print it
PUTH ;make it known it is in hex
LEA DX,MSG3D ;add label
CALL STROUT ;print the label
CRLF ;skip line
;display information on memory FREE
CRLF ;skip a line
LEA DX,MSG3C ;display a message
CALL STROUT ;print it out
;display information on memory FREE
PUTC '<' ;put the angle bracket
MOV DX,MEMTOP ;total memory in para form
SUB DX,MEMBOT ;subtract memory used in para form, still
PUSH DX ;save this itsy bit of info
CALL TOHEX ;convert to hex and display
PUTH ;make it known it is in hex
PUTC '>' ;put closing angle bracket
PUTC TAB ;some space
POP AX ;recover the itsy bit of info
XOR DX,DX ;will be upper byte
MOV BX,10H ;multiply by 16
MUL BX ;dx = msw, ax = lsw
CALL TOHEX ;print most significant word first
MOV DX,AX ;print the lsw now
CALL TOHEX ;print it
PUTH ;make it known it is in hex
LEA DX,MSG3D ;add label
CALL STROUT ;print the label
CRLF ;skip line
POP ES
POP DX ;restore the users registers
POP BX
POP AX
RET
SHOWMEM ENDP
SUBTTL PSP knows all these things, MOREPSP routine
PAGE
;-------------------------------------------------------;
;Procedure: MorePsp ;
; Tells what the PSP has. ;
;In: ;
; Psp variable has the psp segment address ;
;Out: ;
; None ;
;-------------------------------------------------------;
MOREPSP PROC NEAR
PUSH DX ;save callers registers
PUSH DI
PUSH DS
LEA DX,MSG1 ;psp segment address message
CALL Strout ;print out the message to console
MOV DX,PSP ;restore Psp segment address
CALL TOHEX ;print out psp segment in hex to console
PUTH ;print H to represent Hex notation
CRLF ;carriage return/linefeed
LEA DX,MSG2 ;message for the environment area
CALL Strout ;print out the message
MOV DI,PSP ;restore psp segment address
PUSH DS ;save the data segment
MOV DS,DI ;switch segments to PSP
MOV DI,ENVAREA ;point to offset in psp where envarea is stored
MOV DX,[DI] ;dx should have segment address of envarea
POP DS ;restore the data segment
MOV ENV,DX ;env now has that envarea segment
CALL ToHex ;print the address of envarea out
PUTH ;print H to represent Hex notation
CRLF ;carriage return/linefeed
CALL SHOWENV ;show the contents of the environment area
LEA DX,MSG3 ;message for #bytes left in current segment
CALL Strout ;print the message
MOV DI,PSP ;restore psp segment address
PUSH DS ;save current data segment
MOV DS,DI ;switch to psp
MOV DI,SEGLEFT ;point into psp:segleft area
MOV DX,[DI] ;return word at that offset
POP DS ;restore the data segment
CALL ToHex ;and print it out
PUTH ;print H to represent Hex notation
CRLF ;carriage return/linefeed
CALL SHOWMEM ;show psp and its knowledge of memory
POP DS ;restore caller's registers
POP DI
POP DX
RET
MOREPSP ENDP
SUBTTL ROUTINE DATENOW
PAGE
;-------------------------------------------------------;
; Procedure: DateNow ;
; Prints out msg0 and the current date and time ;
;-------------------------------------------------------;
DATENOW PROC NEAR
PUSH AX ;save callers registers
PUSH CX
PUSH DX
PUSH SI
LEA DX,Msg0 ;print the start time message
CALL Strout
MOV AH,Getdate ;getdate func
INT DOS
PUSH CX ;save year
PUSH DX ;save month and date
MOV CL,2 ;since each entry in jmp tble is 4 bytes
SHL AL,CL ;every entry in descrip table is 4bytes
XOR AH,AH ;don't need top
MOV SI,AX ;move day into si (0=sun => 4th byte = 'sun')
LEA DX,DAYS[SI] ;point to verbal description of day and
CALL Strout ;print it out
PUTC ' ' ;insert a blank
POP DX ;restore the month and date
PUSH DX ;still need it later
MOV AL,DH ;get the month
SUB AL,1 ;months start from 1, need initial to be 0
MOV CL,2 ;each entry in table is 4 bytes long.
SHL AL,CL ;so multiply by four
XOR AH,AH
MOV SI,AX ;point to verbal description of month
LEA DX,MONTHS[SI] ;make dx point to the verbal description
CALL Strout ;print it out
PUTC ' ' ;insert a blank
POP DX ;restore month and date
XOR DH,DH ;don't need the month
CALL ToDec ;get the date and convert it
PUTC ',' ;insert a comma
PUTC ' ' ;insert a space
POP CX ;restore the year
MOV DX,CX ;print out the YEAR
CALL ToDECW
POP SI
POP DX
POP CX
POP AX
RET
DATENOW ENDP
SUBTTL Tells the time
PAGE
TIMENOW PROC NEAR
;-----------------------------------------------;
; PROCEDURE: TIMENOW ;
; This procedure prints out the ascii ;
; translation of time onto the console. ;
;-----------------------------------------------;
PUSH AX ;save the caller's registers
PUSH CX
PUSH DX
PUTC ' ' ;put some spaces
PUTC ' ' ;
PUTC ' ' ;
PUTC ' ' ;
PUTC ' ' ;
MOV AH,2CH ;time function for DOS
INT DOS ;get the time
;move the month into register DL, for conversion to decimal
MOV AL,DL ;save the hundreths.
MOV DL,CH ;thats the hour
CALL TODEC ;convert to decimal and write to screen
PUTC ':' ;put in the separator
MOV DL,CL ;thats the minutes
CALL TODEC ;convert minutes to decimal and write it out
PUTC ':' ;put in the separator
MOV DL,DH ;thats the seconds
CALL TODEC ;convert seconds to decimal and write it out
PUTC '.' ;put the separator in
MOV DL,AL ;restore the hundreths of a second
CALL TODEC ;convert hundreths to decimal and write it out
CRLF ;Put a cr/lf
POP DX ;restore caller's registers
POP CX
POP AX
RET
TIMENOW ENDP
SUBTTL Page_Break
PAGE
;-------------------------------------------------------;
;Procedure: Page_Break ;
; Wait for user to press any key. ;
; IN: ;
; None ;
; OUT: ;
; None ;
;-------------------------------------------------------;
PAGE_BREAK PROC NEAR
PUSH AX ;save caller's registers
PUSH DX
CRLF ;put a blank line
LEA DX,MORE ;prompt
CALL STROUT ;print the prompt
CALL STDIN ;wait for character (echos)
CLEAR_SCREEN ;clear out the screen
POP DX ;restore registers
POP AX ;
RET
PAGE_BREAK ENDP
CSEG ENDS
END MAIN